#pragma once
#include <vector>
#include <map>
#include <string>
#include <torch/torch.h>
#include "RinexParser.h"
#include "Common.h"
#include "Utils.h"
#include "Config.h"

struct STECObservation {
    double time;               // GPS时间
    std::string satellite;     // 卫星ID
    std::string station;       // 站点ID
    double latitude;           // 穿刺点纬度
    double longitude;          // 穿刺点经度
    double elevation;          // 高度角
    double azimuth;            // 方位角
    double stec;               // 斜向电子总量(TECU)
    double stecSigma;          // STEC标准差
};

struct VTECObservation {
    double time;               // GPS时间
    std::string satellite;     // 卫星ID
    std::string station;       // 站点ID
    double latitude;           // 穿刺点纬度
    double longitude;          // 穿刺点经度
    double elevation;          // 高度角
    double azimuth;            // 方位角
    double stec;               // 斜向电子总量(TECU)
    double mappingFunction;    // 映射函数值
    double vtec;               // 垂直电子总量(TECU)
};

class STECCalculator {
public:
    STECCalculator();
    ~STECCalculator();

    // 设置观测数据
    void setObservations(const std::vector<GNSSObservation>& observations, const StationInfo& station);
    
    // 设置站点信息
    void setStationInfos(const std::map<std::string, StationInfo>& stationInfos);
    
    // 添加单个站点信息
    void addStationInfo(const std::string& stationName, const StationInfo& info);
    
    // 计算STEC
    void calculateSTEC();
    
    // 获取计算的STEC结果
    std::vector<STECObservation> getSTECObservations() const;

    // Add the missing method declaration
    std::map<std::string, std::vector<GNSSObservation>> groupObservationsBySatellite();

    // 设置电离层等价高度
    void setIonosphereHeight(double height);
    
    // 设置映射函数类型 (SLM, MSLM, TSM)
    void setMappingFunction(const std::string& mappingFunction);
    
    // 根据原始GNSS观测数据计算STEC
    std::vector<STECObservation> calculateSTEC(const std::vector<GNSSObservation>& observations);
    
    // 计算电离层穿刺点
    std::vector<double> calculateIonosphericPiercePoint(const GNSSObservation& obs);
    
    // 将STEC观测值转换为VTEC观测值
    std::vector<VTECObservation> convertSTECToVTEC(const std::vector<STECObservation>& stecObs);
    
    // 按时间分组STEC观测值
    std::map<int, std::vector<STECObservation>> groupSTECByTime(
        const std::vector<STECObservation>& stecObs, 
        int timeInterval = 3600  // 默认按小时分组
    );
    
    // 按卫星分组观测值
    std::map<int, std::vector<GNSSObservation>> groupObservationsBySatellite(
        const std::vector<GNSSObservation>& observations
    );
    
    // 计算映射函数
    double calculateMappingFunction(double elevation);
    
    // 计算考虑方位角的映射函数 (添加水平梯度支持)
    double calculateMappingFunctionWithAzimuth(double elevation, double azimuth, 
                                             double latGrad, double lonGrad);
    
    // 计算STEC值
    double calculateSTECValue(double L1, double L2, double f1, double f2);
    
    // 将观测数据划分为不同的弧段
    std::vector<std::vector<GNSSObservation>> divideObservationsIntoArcs(
        const std::vector<GNSSObservation>& observations
    );
    
    // 使用相位观测值对齐到伪距水平计算STEC
    std::vector<STECObservation> calculatePhaseAlignedSTEC(
        const std::vector<GNSSObservation>& arc
    );

private:
    std::vector<GNSSObservation> observations_;
    StationInfo stationInfo_;
    std::vector<STECObservation> stecObservations_;
    std::map<std::string, StationInfo> stationInfos_;  // 站点信息映射表
    
    double ionoHeight_ = 350.0;  // 电离层等价高度 (km)
    enum class MappingFunctionType { SLM, MSLM, TSM };  // 映射函数类型
    MappingFunctionType mappingFuncType_ = MappingFunctionType::SLM;  // 默认使用SLM
    
    // 不同类型的映射函数实现
    double calculateSLMMappingFunction(double elevation);    // 单层模型映射函数
    double calculateMSLMMappingFunction(double elevation);   // 修正单层模型映射函数
    double calculateTSMMappingFunction(double elevation);    // 薄壳映射函数
    
    // 辅助方法，根据测站名获取测站信息
    StationInfo getStationInfoByName(const std::string& stationName);
    
    // 使用伪距获取STEC
    double calculatePseudorangeSTEC(const GNSSObservation& obs);
    
    // 使用相位获取STEC
    double calculatePhaseSTEC(const GNSSObservation& obs);
    
    // 相位平滑伪距
    void phaseSmoothedPseudorange(std::map<std::string, std::vector<GNSSObservation>>& satelliteGroups);
    
    // 计算电离层穿刺点
    void calculateIonosphericPiercePoint(STECObservation& stecObs, const GNSSObservation& gnssObs);
};